﻿using Microsoft.EntityFrameworkCore;
using Routine.API.Data;
using Routine.API.DtoParameters;
using Routine.API.Entities;
using Routine.API.Helpers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Routine.API.Services
{
    public class CompanyRepository : ICompanyRepository
    {
        private readonly RoutineDbContext context;

        public CompanyRepository(RoutineDbContext context)
        {
            this.context = context ?? throw new ArgumentNullException(nameof(context));
        }
        public void AddCompany(Company company)
        {
            if (null == company)
                throw new ArgumentNullException(nameof(company));

            company.Id = Guid.NewGuid();
            if (company.Employees != null)
            {
                foreach (var item in company.Employees)
                {
                    item.Id = Guid.NewGuid();
                }
            }
            context.Companies.Add(company);
        }

        public void AddEmployee(Guid companyId, Employee employee)
        {
            throw new NotImplementedException();
        }

        public async Task<bool> CompanyExistsAsync(Guid companyId)
        {
            if (companyId == Guid.Empty)
                throw new ArgumentNullException(nameof(companyId));

            return await context.Companies.AnyAsync(o => o.Id == companyId);
        }

        public void DeleteCompany(Company company)
        {
            if (company == null)
                throw new ArgumentNullException(nameof(company));

            context.Companies.Remove(company);
        }

        public void DeleteEmployee(Employee employee)
        {
            throw new NotImplementedException();
        }

        public async Task<IEnumerable<Company>> GetCompaniesAsync()
        {
            return await context.Companies
               .OrderBy(x => x.Name)
               .ToListAsync();
        }

        public Task<PagedList<Company>> GetCompaniesAsync(CompanyDtoParameters parameters)
        {
            throw new NotImplementedException();
        }

        public Task<IEnumerable<Company>> GetCompaniesAsync(IEnumerable<Guid> companyIds)
        {
            throw new NotImplementedException();
        }

        public async Task<Company> GetCompanyAsync(Guid companyId)
        {
            if (companyId == Guid.Empty)
            {
                throw new ArgumentNullException(nameof(companyId));
            }

            return await context.Companies.FirstOrDefaultAsync(x => x.Id == companyId);
        }

        public async Task<Employee> GetEmployeeAsync(Guid companyId, Guid employeeId)
        {
            if (companyId == Guid.Empty)
            {
                throw new ArgumentNullException(nameof(companyId));
            }

            if (employeeId == Guid.Empty)
                throw new ArgumentNullException(nameof(employeeId));

            return await context.Employees.FirstAsync(o => o.CompanyId == companyId && o.Id == employeeId);
        }

        public async Task<IEnumerable<Employee>> GetEmployeesAsync(Guid companyId, string genderDisplay, string q)
        {
            if (companyId == Guid.Empty)
            {
                throw new ArgumentNullException(nameof(companyId));
            }
            if (string.IsNullOrEmpty(genderDisplay) && string.IsNullOrEmpty(q))
            {
                return await context.Employees
                .AsNoTracking()
                .Where(o => o.CompanyId == companyId)
                .ToListAsync();
            }


            var query = context.Employees.Where(o => o.CompanyId == companyId);
            if (!string.IsNullOrEmpty(genderDisplay))
            {
                genderDisplay = genderDisplay.Trim();
                var gender = Enum.Parse<Gender>(genderDisplay);
                query = query.Where(o => o.Gender == gender);
            }

            if (!string.IsNullOrWhiteSpace(q))
            {
                q = q.Trim();
                query = query.Where(o => o.EmployeeNo.Contains(q) || o.FirstName.Contains(q) || o.LastName.Contains(q));
            }

            return await query.ToListAsync();
        }

        public Task<IEnumerable<Employee>> GetEmployeesAsync(Guid companyId, EmployeeDtoParameters parameters)
        {
            throw new NotImplementedException();
        }

        public async Task<bool> SaveAsync()
        {
            return await context.SaveChangesAsync() >= 0;
        }

        public void UpdateCompany(Company company)
        {
            //使用 EF，无需显式地声明
            //context.Entry(company).State = EntityState.Modified;
        }

        public void UpdateEmployee(Employee employee)
        {
            throw new NotImplementedException();
        }
    }
}
